package cn.echogo.framework.widget;

import android.content.Context;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.MenuItem.OnMenuItemClickListener;
import android.view.View.MeasureSpec;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.Scroller;
import android.widget.FrameLayout.LayoutParams;

public class EGScrollLayout extends FrameLayout {

	private static final String tag = EGScrollLayout.class.getSimpleName();

	private static final int TOUCH_STATE_REST = 0;
	private static final int TOUCH_STATE_SCROLLING = 1;
	private static final int SNAP_VELOCITY = 300; // 速度

	private Scroller mScroller;
	private VelocityTracker mVelocityTracker;

	private OnScrollFinishedListener mOnScrollFinishedListener;

	private int mTouchState = TOUCH_STATE_REST;
	private int mTouchSlop;
	private float mLastMotionX;
	private float mLastMotionY;
	private int[] mStops = { -320, 0, 250, 320 };
	// private int[] mStops = {0, 250};
	private int mCurrStopIndex = 0;
	private boolean mOutOfBound; // 超出边界

	public EGScrollLayout(Context context) {
		super(context);
		init();
	}

	public EGScrollLayout(Context context, AttributeSet attrs) {
		super(context, attrs);
		init();
	}

	public EGScrollLayout(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		init();
	}

	private void init() {
		mScroller = new Scroller(getContext());
		mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
	}

	@Override
	public boolean onInterceptTouchEvent(MotionEvent ev) {
		final int action = ev.getAction();
		final float x = ev.getX();
		final float y = ev.getY();
		switch (action) {
		case MotionEvent.ACTION_DOWN:
			Log.v(tag, "onInterceptTouchEvent.ACTION_DOWN");
			mLastMotionX = x;
			mLastMotionY = y;
			mTouchState = mScroller.isFinished() ? TOUCH_STATE_REST : TOUCH_STATE_SCROLLING;
			break;
		case MotionEvent.ACTION_MOVE:
			Log.v(tag, "onInterceptTouchEvent.ACTION_DOWN");
			int deltaX = (int) (mLastMotionX - x);
			int deltaY = (int) (mLastMotionY - y);
			if (Math.abs(deltaY) > Math.abs(deltaX * 0.9)) {
				return false;
			}
			if (deltaX > mTouchSlop) {
				mTouchState = TOUCH_STATE_SCROLLING;
			}
			break;

		case MotionEvent.ACTION_UP:
		case MotionEvent.ACTION_CANCEL:
			Log.v(tag, "onInterceptTouchEvent.ACTION_DOWN");
			mTouchState = TOUCH_STATE_REST;
			break;
		}
		return mTouchState != TOUCH_STATE_REST;

	}

	@Override
	public boolean onTouchEvent(MotionEvent event) {
		if (mVelocityTracker == null) {
			mVelocityTracker = VelocityTracker.obtain();
		}
		mVelocityTracker.addMovement(event);
		final int action = event.getAction();
		final float x = event.getX();
		final float y = event.getY();
		switch (action) {
		case MotionEvent.ACTION_DOWN:
			Log.v(tag, "onTouchEvent.ACTION_DOWN");
			if (!mScroller.isFinished()) {
				mScroller.abortAnimation();
			}
			mLastMotionX = x;
			break;
		case MotionEvent.ACTION_MOVE:
			Log.v(tag, "onTouchEvent.ACTION_MOVE");
			int deltaX = (int) (mLastMotionX - x);
			mLastMotionX = x;
			scrollBy(deltaX, 0);
			break;
		case MotionEvent.ACTION_UP:
			Log.v(tag, "onTouchEvent.ACTION_UP");
			final VelocityTracker velocityTracker = mVelocityTracker;
			velocityTracker.computeCurrentVelocity(1000);
			int velocityX = (int) velocityTracker.getXVelocity(); // velocityTracker.getXVelocity(),
																	// 向左滚动为负数,
																	// 向右滚动为正数（注意，与Scrollrer相反）
			if (velocityX < -SNAP_VELOCITY && mCurrStopIndex > 0) { // 向左滚动一格
				snapToStop(mCurrStopIndex - 1);
			} else if (velocityX > SNAP_VELOCITY && mCurrStopIndex < mStops.length - 1) { // 向右滚动一格
				snapToStop(mCurrStopIndex + 1);
			} else {
				snapToNearbyStop();
			}

			if (mVelocityTracker != null) {
				mVelocityTracker.recycle();
				mVelocityTracker = null;
			}
			mTouchState = TOUCH_STATE_REST;
			break;
		case MotionEvent.ACTION_CANCEL:
			mTouchState = TOUCH_STATE_REST;

		}

		return true;
	}

	@Override
	protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
		Log.d(tag, "onLayout");
		// int childLeft = mStops[mCurrStopIndex];
		int childLeft = 0;
		// int childTop = 0;
		final int count = getChildCount();
		for (int i = 0; i < count; i++) {
			final View child = getChildAt(i);
			if (child.getVisibility() != GONE) {
				final int childWidth = child.getMeasuredWidth();
				final int childHeight = child.getMeasuredHeight();
				int childRight = childLeft + childWidth;
				// int childBottom = childTop + childHeight;
				child.layout(childLeft, 0, childRight, childHeight);
				childLeft = childRight;
				// childTop = childBottom;
			}
		}
	}

	// @Override
	// protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
	// //初始化时调了2次，滚动时，此值不会变化
	// super.onMeasure(widthMeasureSpec, heightMeasureSpec);
	//
	// final int width = MeasureSpec.getSize(widthMeasureSpec);
	// final int widthMode = MeasureSpec.getMode(widthMeasureSpec);
	//
	// if(widthMode == MeasureSpec.EXACTLY) { //FOR TEST
	// Log.v(tag, "onMeasure.EXACTLY = " + width);
	// } else if(widthMode == MeasureSpec.AT_MOST) {
	// Log.v(tag, "onMeasure.AT_MOST = " + width);
	// } else if(widthMode == MeasureSpec.UNSPECIFIED) {
	// Log.v(tag, "onMeasure.UNSPECIFIED = " + width);
	// } else {
	// Log.v(tag, "onMeasure. = " + width);
	// }
	//
	//
	//
	// final int count = getChildCount();
	// for (int i = 0; i < count; i++) {
	// View child = getChildAt(i);
	// child.measure(widthMeasureSpec, heightMeasureSpec);
	// }
	//
	// // scrollTo(200, 0);
	// }

	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		Log.d(tag, "onMeasure");
		super.onMeasure(widthMeasureSpec, heightMeasureSpec);
		
		final int width = MeasureSpec.getSize(widthMeasureSpec);
		final int widthMode = MeasureSpec.getMode(widthMeasureSpec);
		if (widthMode != MeasureSpec.EXACTLY) {
			throw new IllegalStateException("ScrollLayout only canmCurScreen run at EXACTLY mode!");
		}

		final int heightMode = MeasureSpec.getMode(heightMeasureSpec);
		if (heightMode != MeasureSpec.EXACTLY) {
			throw new IllegalStateException("ScrollLayout only can run at EXACTLY mode!");
		}

		// The children are given the same width and height as the scrollLayout
		final int count = getChildCount();
		for (int i = 0; i < count; i++) {
			getChildAt(i).measure(widthMeasureSpec, heightMeasureSpec);
		}
		
		scrollTo(-mStops[mCurrStopIndex], 0); //
	}

	@Override
	public void computeScroll() {
		if (mScroller.computeScrollOffset()) {
			scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
			postInvalidate();
		}
	}

	public void snapToStop(int stopIndex) {
		Log.d(tag, "snapToStop = " + stopIndex);
		mCurrStopIndex = stopIndex;
		final int scrollX = getScrollX();
		final int cooX = -scrollX; // X坐标
		if (cooX != mStops[stopIndex]) {
			final int delta = -mStops[stopIndex] - scrollX;
			mScroller.startScroll(scrollX, 0, delta, 0, 500);
			invalidate();
		}

	}

	public void snapToNearbyStop() {
		int preStopIndex = 0;
		int nextStopIndex = mStops.length - 1;
		final int thisStop = -getScrollX(); // 注意正负
		for (int i = 0; i < mStops.length; i++) {
			if (thisStop > mStops[i]) {
				preStopIndex = i;
				continue;
			}
			if (thisStop < mStops[i]) {
				nextStopIndex = i;
				break;
			}
		}
		int midVal = (mStops[preStopIndex] + mStops[nextStopIndex]) / 2;
		int nearbyStopIndex = (thisStop < midVal ? preStopIndex : nextStopIndex);
		Log.d(tag, "thisStop :: " + thisStop + ", snapToNearbyStop :: " + preStopIndex + ", " + nextStopIndex);
		snapToStop(nearbyStopIndex);
	}

	public void setOnScrollFinishedListener(OnScrollFinishedListener listener) {
		this.mOnScrollFinishedListener = listener;
	}

	public interface OnScrollFinishedListener {

		void onScrollFinished(int stopIndex);

	}

}
